import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map.Entry;

public class Classification {

	public ArrayList<Integer> KNeighbors(int k,
			HashMap<Integer, Double> similarities) {

		ArrayList<Double> vals = new ArrayList<Double>(similarities.values());

		ArrayList<Integer> resultIndexes = new ArrayList<>();
		ArrayList<Integer> resultKeys = new ArrayList<>();

		for (int i = 0; i < k; i++) {
			Double maxVal = 0.0;
			Integer maxValIndex = 0;
			for (int j = 0; j < vals.size(); j++) {
				if (vals.get(j) > maxVal) {
					maxVal = vals.get(j);
					maxValIndex = j;
				}
			}
			resultIndexes.add(maxValIndex);
			vals.set(maxValIndex, 0.0);
		}

		int index = 0;

		for (Entry<Integer, Double> entry : similarities.entrySet()) {
			for (int m = 0; m < resultIndexes.size(); m++) {
				if (index == resultIndexes.get(m)) {
					resultKeys.add(entry.getKey());
					break;
				}
			}
			index++;
		}

		return resultKeys;
	}

	public ArrayList<Similarity> calculateSimilarity(int k) {

		ArrayList<Similarity> nullEvaluations = new ArrayList<>();
		HashMap<Integer, User> data = ReadData.getMoviesEvaluated();

		data = ReadData.getMoviesToBeEvaluated(data);
		HashMap<Integer, Movie> movies = ReadData.getMoviesWithFeatures();

		HashMap<Integer, Double> similarities;

		int points = 0;
		double result = 0.0;

		for (Entry<Integer, User> entry : data.entrySet()) {
			User user = entry.getValue();
			System.out.println("k = " + k + ", userId = " + user.userId);
			for (Evaluation unknownEvaluation : user.notEvaluatedMovies) {
				similarities = new HashMap<>();
				
				Movie unknown_movie = null;
				Movie any_movie = null;
				
				for (Entry<Integer, Movie> movie : movies.entrySet()) {
					if (unknownEvaluation.movieId == movie.getValue().movieId) {
						unknown_movie = movie.getValue();
						break;
					}
				}

				for (Entry<Integer, Movie> entry_movie : movies.entrySet()) {
					if (unknownEvaluation.movieId != entry_movie.getValue().movieId) {
						any_movie = entry_movie.getValue();
						if (any_movie != null && unknown_movie != null) {
							points = 0;
							result = 0.0;
							for (int i = 0; i < unknown_movie.features.size(); i++) {
								if (unknown_movie.features.get(i).value
										.toString().equals(
												any_movie.features.get(i).value
														.toString())) {
									
									int weight;
									if (i == 0 || i > 18)
										weight = 1;
									else if (i > 0 && i <= 5)
										weight = 2;
									else if (i > 5 && i <= 8)
										weight = 4;
									else if (i > 8 && i <= 14)
										weight = 16;
									else
										weight = 8;

									points += weight;
								}
							}
							result = (Double) (points / 154.0);
							similarities.put(any_movie.movieId, result);
						}
					}
				}

				ArrayList<Integer> similarMovieIds = KNeighbors(k, similarities);
				int sum = 0;

				for (Integer id : similarMovieIds) {
					for (Evaluation eval : user.evaluatedMovies) {
						if (eval.movieId == id) {
							sum += Integer.parseInt(eval.evaluation);
							break;
						}
					}
				}


				int evaluationOfUnknownMovie = Math.round(sum / k);
				Similarity sim = new Similarity(user.userId,
						unknown_movie.movieId, evaluationOfUnknownMovie);
				nullEvaluations.add(sim);
			}
		}

		return nullEvaluations;
	}
}
